package com.feidee.data.email.handler;

import com.feidee.data.email.dao.ConfDao;
import com.feidee.data.email.model.EConstant;
import com.feidee.data.email.model.EmailConf;
import com.feidee.data.email.model.EmailLogModel;
import com.feidee.data.email.model.ScheduleJob;
import com.feidee.data.email.util.ApplicationContextUtil;
import com.feidee.data.email.util.EmailUtil;
import com.feidee.data.email.util.QuartzJobFactory;
import com.feidee.data.report.exception.DataDaoException;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.Calendar;

@Component
public class TimerRunner {

	private SchedulerFactoryBean schedulerFactoryBean;
	private static final Logger LOG = LoggerFactory.getLogger(TimerRunner.class);
	@Resource
	private ConfDao confDao;

	public void run() {
		if (!EConstant.TIME_SWITCH) {
			return;
		}
		LOG.info("执行每日定时任务:读取邮件配置,创建定时任务\ttime=" + EmailUtil.getNowTime());
		if (schedulerFactoryBean == null) {
			schedulerFactoryBean = ApplicationContextUtil.getBean(SchedulerFactoryBean.class);
		}
		List<EmailConf> emailConfs = null;
		try {
			emailConfs = confDao.listRunEmail();
			LOG.info("获取到所有邮件的run_date信息,邮件的条数为" + emailConfs.size());
		} catch (DataDaoException e) {
			e.printStackTrace();
		}
		if (emailConfs == null) {
			LOG.info("获取邮件run_date信息异常");
			return;
		}
		Scheduler scheduler = schedulerFactoryBean.getScheduler();

		// 删除现在正在执行的任务
		List<JobExecutionContext> currentlyExecutingJobs = null;
		try {
			currentlyExecutingJobs = scheduler.getCurrentlyExecutingJobs();
			for (JobExecutionContext executionjob : currentlyExecutingJobs) {
				JobDetail jobDetail = executionjob.getJobDetail();
				JobKey key = jobDetail.getKey();
				try {
					scheduler.deleteJob(key);
				} catch (SchedulerException e) {
					LOG.info("删除定时任务 " + key.getGroup() + "组" + key.getName() + "失败");
					e.printStackTrace();
				}
			}
		} catch (SchedulerException e) {
			LOG.info("获取当前定时任务失败!");
			e.printStackTrace();
		}

		for (EmailConf conf : emailConfs) {
			long start = System.currentTimeMillis();
			String starttime = EmailUtil.getNowTime();
			try {
				if (!isTodayRun(conf.getRun_date())) {
					continue;
				}
				ScheduleJob job = new ScheduleJob();
				job.setJobGroup("data_work");
				job.setJobName(conf.getEmail_key());
				job.setCronExpression(buildRuntime(conf.getRun_date()));
				job.setJobStatus("1");
				job.setJobId(UUID.randomUUID().toString().replace("-", ""));
				LOG.info("创建定时任务: group=" + job.getJobGroup() + " name=" + job.getJobName() + " runtime="
						+ job.getCronExpression());
				TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
				CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
				if (null == trigger) {
					JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)
							.withIdentity(job.getJobName(), job.getJobGroup()).build();
					jobDetail.getJobDataMap().put("scheduleJob", job);
					// 表达式调度构建器
					CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
					// 按新的cronExpression表达式构建一个新的trigger
					trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())
							.withSchedule(scheduleBuilder).build();
					scheduler.scheduleJob(jobDetail, trigger);
				} else {
					// Trigger已存在，那么更新相应的定时设置
					// 表达式调度构建器
					CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
					// 按新的cronExpression表达式重新构建trigger
					trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder)
							.build();
					// 按新的trigger重新设置job执行
					scheduler.rescheduleJob(triggerKey, trigger);
				}
				long end = System.currentTimeMillis();
				EmailLogModel logs = new EmailLogModel();
				logs.setEmail_key(conf.getEmail_key());
				logs.setProcess("submit");
				logs.setIndex(0);
				logs.setStatus("Successfully");
				logs.setMessage("time: " + job.getCronExpression());
				logs.setCost((int) (end - start));
				logs.setStarttime(starttime);
				EmailUtil.sendLog(logs);
			} catch (Exception e) {
				e.printStackTrace();
				long end = System.currentTimeMillis();
				EmailLogModel logs = new EmailLogModel();
				logs.setEmail_key(conf.getEmail_key());
				logs.setProcess("submit");
				logs.setIndex(0);
				logs.setStatus("Failed");
				logs.setMessage(e.getMessage());
				logs.setCost((int) (end - start));
				logs.setStarttime(starttime);
				EmailUtil.sendLog(logs);
			}
		}
	}

	/**
	 * 判断今天是否run
	 *
	 * @param run_date
	 *            格式:*(分钟) *(小时) *(日) *(月) *(星期以/分割)
	 * @return
	 */
	private boolean isTodayRun(String run_date) {
		Calendar calendar = Calendar.getInstance();
		Date date = new Date();
		calendar.setTime(date);
		String[] split = run_date.split(" ");
		if (split.length != 5) {
			return false;
		}
		if (!"*".equals(split[2])) {
			int day = Integer.parseInt(split[2]);
			if (day != calendar.get(Calendar.DAY_OF_MONTH)) {
				return false;
			}
		}
		if (!"*".equals(split[3])) {
			int month = Integer.parseInt(split[3]);
			if (month != calendar.get(Calendar.MONDAY)) {
				return false;
			}
		}
		if (!"*".equals(split[4])) {
			String[] dayofWeeks = split[4].split("/");
			boolean isRun = false;
			for (String dayOfWeekStr : dayofWeeks) {
				int dayOfWeek = Integer.parseInt(dayOfWeekStr);
				if (dayOfWeek == calendar.get(Calendar.DAY_OF_WEEK)) {
					isRun = true;
				}
			}
			if (!isRun) {
				return false;
			}
		}
		return true;
	}

	private String buildRuntime(String run_date) {
		Calendar calendar = Calendar.getInstance();
		Date date = new Date();
		calendar.setTime(date);
		String[] split = run_date.split(" ");
		String min = split[0];
		String hour = split[1];
		return "00 " + min + " " + hour + " " + calendar.get(Calendar.DAY_OF_MONTH) + " "
				+ (calendar.get(Calendar.MONTH) + 1) + " " + "?" + " " + calendar.get(Calendar.YEAR);
	}

	public static void main(String[] args) {
		TimerRunner timerRunner = new TimerRunner();
		boolean todayRun = timerRunner.isTodayRun("30 10 * * 2");
		System.out.println(todayRun);
	}
}